#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <queue>
#include <ctime>
using namespace std;
#include "BlockQueue.hpp"
#include "Task.hpp"

// int addfunc(int x,int y)
// {
//     return x+y;
// }

template <class C, class S>
class BlockQueueS
{
public:
    BlockQueue<C> *_c_bq; //生产消费队列
    BlockQueue<S> *_s_bq; //保存队列
};

void *consumer(void *args) // 生产者线程需要做的事情
{
    BlockQueue<CalTask> *c_bq = (static_cast<BlockQueueS<CalTask, SaveTask> *>(args))->_c_bq;
    BlockQueue<SaveTask> *s_bq = (static_cast<BlockQueueS<CalTask,SaveTask> *>(args))->_s_bq;
    while (true)
    {
        // 从共享资源中拿数据
        CalTask t;
        c_bq->pop(&t);
        // 计算结果：
        string result = t();
        cout<<"计算任务完成"<<result<<endl;
        // cout<<"计算数据完成"<<endl;
        // cout << "从队列中拿到数据：" << t() << endl;
        // 消费变慢
        //发送保存数据
        // SaveTask s(result,Save);
        // s_bq->push(s);//把数据放入队列中
        // cout<<"推送保存任务完成"<<endl;
        // sleep(1);
    }
    return nullptr;
}

void *proctor(void *args) // 消费者线程需要做的事情
{
    BlockQueue<CalTask> *c_bq = (static_cast<BlockQueueS<CalTask, SaveTask> *>(args))->_c_bq;
    while (true)
    {
        // 从共享资源中写数据
        // int data = rand()%10+1;//生产1到10的随机数
        int x = rand() % 10 + 1; // 生产1到10的随机数
        int y = rand() % 5 + 1;  // 生产1到5的随机数
        int op_code = rand() % 5;
        CalTask t(x, y, mymath, str[op_code]);
        c_bq->push(t);
        // 打印结果：
        cout << t.ToString() << endl;
        // cout<<"发送数据完成"<<endl;
        // cout << "生产数据到队列中：" << data << endl;
        // cout << "生产数据到队列中：" << x << " : "<< y << endl;
        // sleep(1);//看清现象，生产变慢
    }
    return nullptr;
}

// void *saver(void *args)
// {
//     BlockQueue<SaveTask> *s_bq = (static_cast<BlockQueueS<CalTask,SaveTask> *>(args))->_s_bq;
//     while(true)
//     {
//         SaveTask s;
//         s_bq->pop(&s);
//         s();
//         cout<<"保存任务完成"<<endl;
//     }
//     return nullptr;
// }

int main()
{
    // 创建随机数
    srand((unsigned long)time(nullptr) ^ getpid());
    // 创建阻塞队列
    // BlockQueue<Task> *bq = new BlockQueue<Task>();
    BlockQueueS<CalTask, SaveTask> bq;
    bq._c_bq = new BlockQueue<CalTask>();
    bq._s_bq = new BlockQueue<SaveTask>();
    // 创建线程
    //pthread_t c, p, s; // 生产者和消费者以及保存者
    //多线程也可以同时运行
    pthread_t c[3], p[2];
    pthread_create(c, nullptr, consumer, (void *)&bq);
    pthread_create(c+1, nullptr, consumer, (void *)&bq);
    pthread_create(c+2, nullptr, consumer, (void *)&bq);
    pthread_create(p, nullptr, proctor, (void *)&bq);
    pthread_create(p+1, nullptr, proctor, (void *)&bq);
     
    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(c[2], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);


    // pthread_create(&c, nullptr, consumer, (void *)&bq);
    // pthread_create(&p, nullptr, proctor, (void *)&bq);
    // pthread_create(&s, nullptr, saver, (void *)&bq);

    // // 线程等待
    // pthread_join(c, nullptr);
    // pthread_join(p, nullptr);
    // pthread_join(s, nullptr);
    return 0;
}